package com.imflea.zero.model.entity.delivery;

import com.imflea.zero.model.entity.delivery.dto.ProductDeliveryRuleDto;
import com.imflea.zero.model.entity.delivery.dto.RuleRecord;
import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Rule;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.api.RulesEngineParameters;
import org.jeasy.rules.core.DefaultRulesEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;

/**
 * @author zhaoyang
 * @version 1.0
 * @project farmplus-service
 * @package com.imflea.zero.service.delivery
 * @filename 创建时间: 2021/11/4
 * @description
 * @copyright Copyright (c) 2021 中国软件与技术服务股份有限公司
 */
public class DeliveryRuleSet {

    private static Logger logger = LoggerFactory.getLogger(DeliveryRuleSet.class);

    /*
        NOTE: 快递费用是由区域和购买数量两个维度确定的
              计算时,首先从配置的区域与收货地址进行匹配找到最优的匹配值
     */
    @Rule(name = "MatchRegion1Rule", description = "匹配省市区规则")
    public static class MatchRegion1Rule {


        private RuleRecord record;

        public MatchRegion1Rule(RuleRecord record) {
            this.record = record;
        }


        @Condition
        public boolean when(@Fact("param") ProductDeliveryRuleDto param) {

            String province = param.getReceiverProvince();

            String city = param.getReceiverCity();

            return province.equals(record.getProvince()) && city.equals(record.getCity());
        }


        @Action
        public void then() {

            record.setMatch(true);
            logger.info("匹配省市区规则");
        }
    }

    @Rule(name = "MatchRegion2Rule", description = "匹配省规则")
    public static class MatchRegion2Rule {


        private RuleRecord record;

        public MatchRegion2Rule(RuleRecord record) {
            this.record = record;
        }

        @Condition
        public boolean when(@Fact("param") ProductDeliveryRuleDto param) {

            String province = param.getReceiverProvince();

            return province.equals(record.getProvince());
        }

        @Action
        public void then() {

            record.setMatch(true);
            logger.info("匹配省规则");
        }
    }

    @Rule(name = "MatchRegion3Rule", description = "匹配默认规则,默认规则是未配置省市规则")
    public static class MatchRegion3Rule {


        private RuleRecord record;

        public MatchRegion3Rule(RuleRecord record) {
            this.record = record;
        }

        @Condition
        public boolean when(@Fact("param") ProductDeliveryRuleDto param) {
            return record.getProvince().isEmpty() && record.getCity().isEmpty();
        }

        @Action
        public void then() {

            record.setMatch(true);
            logger.info("匹配默认规则");
        }
    }


    @Rule(name = "MatchFreePriceRule", description = "免运费")
    public static class MatchFreePriceRule {

        private RuleRecord record;

        public MatchFreePriceRule(RuleRecord record) {
            this.record = record;
        }

        @Condition
        public boolean when() {
            return record.getQuantity() >= record.getFreeCount();
        }

        @Action
        public void then() {

            record.setMoney(new BigDecimal(0));
            logger.info("免运费");
        }
    }

    @Rule(name = "MatchStartPriceRule", description = "起步价")
    public static class MatchStartPriceRule {

        private RuleRecord record;

        public MatchStartPriceRule(RuleRecord record) {
            this.record = record;
        }

        @Condition
        public boolean when() {
            return record.getQuantity() < record.getStartCount();
        }

        @Action
        public void then() {
            // note 起步价 X 商品数量 为运费
            record.setMoney(record.getStartPrice().multiply(new BigDecimal(record.getQuantity())));
            logger.info("起步运费:{}", record.getMoney());
        }
    }

    @Rule(name = "MatchNormalPriceRule", description = "匹配阶梯价规则")
    public static class MatchNormalPriceRule {

        private RuleRecord record;

        public MatchNormalPriceRule(RuleRecord record) {
            this.record = record;
        }

        @Condition
        public boolean when() {

            return record.getQuantity() >= record.getStartCount();
        }

        @Action
        public void then() {
            // NOTE: （阶梯价）* (商品数量) = 运费
            record.setMoney(record.getNormalPrice().multiply(new BigDecimal(record.getQuantity())));
            logger.info("阶梯运费:{}", record.getMoney());
        }
    }


    //  配送区域规则集
    public static void RegionRuleFire(RuleRecord record, ProductDeliveryRuleDto param) {

        // 匹配规则就跳过后面的规则
        RulesEngineParameters parameters = new RulesEngineParameters().skipOnFirstAppliedRule(true);
        RulesEngine regionRuleEngine = new DefaultRulesEngine(parameters);

        Rules rules = new Rules();
        rules.register(new MatchRegion1Rule(record));
        rules.register(new MatchRegion2Rule(record));
        rules.register(new MatchRegion3Rule(record));

        Facts facts = new Facts();
        facts.put("param", param);
        regionRuleEngine.fire(rules, facts);
    }


    //  运费规则集
    public static void PriceRuleFire(RuleRecord record) {

        RulesEngineParameters parameters = new RulesEngineParameters().skipOnFirstAppliedRule(true);
        RulesEngine priceRuleEngine = new DefaultRulesEngine(parameters);

        Rules rules = new Rules();
        rules.register(new MatchFreePriceRule(record));
        rules.register(new MatchStartPriceRule(record));
        rules.register(new MatchNormalPriceRule(record));

        priceRuleEngine.fire(rules, new Facts());
    }
}
